package main

import (
	"../dmap"
	"encoding/json"
	"github.com/op/go-logging"
	"github.com/valyala/fasthttp"
	"gopkg.in/alecthomas/kingpin.v2"
	"io/ioutil"
	"os"
	"strings"
	//_ "net/http/pprof"
	"runtime"
)

func init() {
	var logBackend = logging.NewLogBackend(os.Stdout, "", 0)
	format := logging.MustStringFormatter(
		`%{color}%{time:2006-01-02 15:04:05.000} %{shortfunc} %{level:.4s} %{id:03x}%{color:reset} %{message}`)
	logging.SetFormatter(format)
	logging.SetBackend(logBackend)
	runtime.GOMAXPROCS(runtime.NumCPU())
}

var LOG = logging.MustGetLogger("router")

func main() {
	//go func() {
	//    fmt.Println(http.ListenAndServe("0.0.0.0:6060", nil))
	//}()

	logging.SetLevel(logging.INFO, "router")
	timeout := kingpin.Flag("timeout", "timeout").Default("3").Int()
	port := kingpin.Flag("port", "port").Default("8085").String()
	baseStr := kingpin.Flag("base_backends", "base_backends").String()
	etcds := kingpin.Flag("etcd_addrs", "etcd_addrs").String()
	user := kingpin.Flag("etcd_user", "etcd_user").String()
	passwd := kingpin.Flag("etcd_passwd", "etcd_passwd").String()
	etcdbasepath := kingpin.Flag("etcd_base_path", "etcd_base_path").String()
	cacheMappingFile := kingpin.Flag("cache_mapping_file", "cache_mapping_file").Default("mapping.json").ExistingFile()
	queryAllOnCacheMiss := kingpin.Flag("query_all_on_cache_miss", "query_all_on_cache_miss").Bool()
	queryBackends := kingpin.Flag("query_backends", "query_backends").Bool()
	keyMethodStr := kingpin.Flag("key_method", "key_method").Default("all").String()
	kingpin.Parse()
	url2Key := KeyAsDefault
	switch *keyMethodStr {
	case "filename":
		url2Key = KeyAsParamFileName
	case "last":
		url2Key = KeyAsLast
	case "2rd":
		url2Key = KeyAsSecond
	}
	cached := make(map[string]string)
	if content, err := ioutil.ReadFile(*cacheMappingFile); err == nil {
		json.Unmarshal(content, &cached)
	} else {
		LOG.Errorf("load json format err: %v", err)
		os.Exit(1)
	}
	LOG.Infof("loaded from %s mapping: %v \n", *cacheMappingFile, cached)
	baseAddrs := strings.Split(*baseStr, ",")

	var mapping *dmap.EtcdDistributeMap
	if *etcds != "" && *etcdbasepath != "" {
		etcdAddrs := strings.Split(*etcds, ",")
		var err error
		mapping, err = dmap.NewDistributeMap(*etcdbasepath, "", *user, *passwd, etcdAddrs, 3)
		if err != nil {
			LOG.Errorf("init dmap err: %v", err)
			os.Exit(1)
		}
	}
	router := &Router{
		baseBackends:        baseAddrs,
		timeout:             *timeout,
		queryAllOnCacheMiss: *queryAllOnCacheMiss,
		queryBackends:       *queryBackends,
		cacheBackends:       cached,
		mapping:             mapping,
		GetKeyFunc:          url2Key,
	}

	if err := router.init(); err != nil {
		LOG.Errorf("init router: %v", err)
		os.Exit(1)
	}
	LOG.Infof("starting on port %s", *port)
	server := &fasthttp.Server{
		Handler:           router.handler,
		ReadBufferSize:    1024 * 4,
		WriteBufferSize:   1024 * 4,
		ReduceMemoryUsage: true,
		DisableKeepalive:  true,
	}
	err := server.ListenAndServe(":" + *port)
	if err != nil {
		LOG.Errorf("server error %v", err)
		os.Exit(2)
	}
}
